﻿/*

roseUI.js

Copyright (C) 2012 Fraunhofer Institute for Secure Information Technology

Authors: Steven Arzt <steven.arzt@sit.fraunhofer.de>
         Oliver Hoffmann <oliver.hoffmann@sit.fraunhofer.de>
         Sebastian Ruhleder <sebastian.ruhleder@sit.fraunhofer.de>
         
Contact: Andreas Poller <andreas.poller@sit.fraunhofer.de>
         Fraunhofer Institute for Secure Information Technology
         Rheinstraße 75
         64295 Darmstadt
         Germany

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/gpl-3.0.txt>.

*/

// =============================================================================
// TODO:
//  - Privacy der E-Mail-Adressen
// =============================================================================
var user_id = null;
var language = "en";

$(document).ready(function() {
    // Set open/close interaction filter checkbox.
    $("#showopenclose").attr('checked', window.SHOW_OPEN_CLOSE_INTERACTIONS);

    // Register handler for open/close interaction filter checkbox.
    $(document).on('click', "#showopenclose", function() {
        // Set global variable.
        window.SHOW_OPEN_CLOSE_INTERACTIONS = $(this).is(':checked');

        // Display interactions.
        displayInteractions();
    });
});

// =============================================================================
//if (!$)
//    var $ = null;
// =============================================================================
// Handler function for loading the JQuery API and calling the given handler.
// Parameters:
//      - handler       The handler function to call when JQuery has loaded
//      - handlerData   A custom parameter to be passed to the handler function.

function loadJQuery(handler, handlerData) {
    log('Loading JQuery ...');
    if (typeof kango == 'undefined') {
        log("Kango not available");
        return;
    }

    try {
        // jQuery initialization
        (function(callback) {
            try {
                kango.xhr.send({
                    url: 'http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js',
                    contentType: 'text'
                }, function(data) {
                    log('JQuery js file loaded.');
                    eval(data.response.toString());
                    callback(window.$.noConflict(true));
                });
            } catch (ex) {
                log("Could not load JQuery: " + ex);
            }
        })(function(obj) {
            // Make sure that all the different kinds of accessing jQuery in the
            // various libraries are satisfied
            if (!$) {
                $ = obj;
            }
            if (!window.$) {
                window.$ = obj;
            }

            // Continue with the initialization process
            handler(handlerData);
        });
    } catch (ex) {
        log("Could not load JQuery: " + ex);
    }
}

// ---------------------------------------------------------------------------
// Loads an external library. This function assumes that the current window
// is the top window and that JQuery is already available.
// Parameters:
//      liburl:     URL of the library to be loaded
//      handler:    Function to be called when done (accepts one parameter)
//      hdata:      Data to be passed to the handler function

function loadLibrary(liburl, handler, hdata) {
    kango.xhr.send({
        url: liburl,
        contentType: 'text'
    }, function(data) {
        try {
            eval(data.response.toString());
        } catch (ex) {
            throw new Error("Could not load external library: " + ex);
        }
        handler(hdata);
    });
}

// =============================================================================
// Bootstrapper function for initializing the ROSE UI.

function initializeROSEUI(step) {
    if ((typeof step === undefined) || !step) step = 1;

    log('Initializing GUI (step ' + step + ')...');
    try {
        if (step == 1) {
            if ((typeof $ == "undefined") || !$) {
                log("JQuery not available, loading...");
                loadJQuery(initializeROSEUI, 2);
            } else {
                log("JQuery available");
                initializeROSEUI(2);
            }
        } else if (step == 2) {
            $("#loadMessage").show();

            // Check whether the JSON library is already available. If not, load
            // it, otherwise directly continue.
            if (typeof jQuery.parseJSON != "undefined") {
                log("JSON library available");
                initializeROSEUI(3);
            } else {
                log("JSON library NOT available, loading...");
                loadLibrary('http://jquery-json.googlecode.com/files/jquery.json-2.3.min.js', initializeROSEUI, 3);
            }
        } else if (step == 3) {
            loadLanguage(initializeROSEUI, 4);
        } else if (step == 4) {
            loadLanguageContent(language, initializeROSEUI, 5);
        } else if (step == 5) {
            if (typeof initStorage != "undefined") {
                log("Initializing storage...");
                initStorage();
            }
            initializeVersionInfo();
            log("Version Info initialized");
            initializeMenu();
            log("Menu initialized");
            $("#loadMessage").hide();
        } else throw new Error("Invalid initialization step");
    } catch (ex) {
        log("Could not initialize UI: " + ex);
    }
}

// =============================================================================

function loadLanguage(handler, hdata) {
    log("Loading language settings...");


    // Set the browser language as a fallback
    if (navigator.language && navigator.language.indexOf("en") >= 0) {
        language = "en";
    } else if (navigator.language && navigator.language.indexOf("de") >= 0) {
        language = "de";
    }

    if (handler === undefined) {
        return;
    } else {
        handler(hdata);
    }
    // Try to get the Facebook language settings
    // loadUserID(function() {
    //     // If we are not logged into Facebook, we use the browser language
    //     if (user_id === null) {
    //         log("Facebook user ID not available");
    //         handler(hdata);
    //         return;
    //     }


    //     // Load the Facebook settings page
    //     log("Loading Facebook language settings for user '" + user_id + "'...");
    //     var url = "https://www.facebook.com/ajax/settings/account/language.php?" + "__a=1&__user=" + user_id; // 1539378569
    //     $("#dataFBLang").load(url, null, function(response, status, xhr) {
    //         var s = response.replace("for (;;);", "");
    //         var payload = jQuery.parseJSON(s)["domops"][0][3];
    //         payload = payload.substring(payload.indexOf('HTML("') + 'HTML("'.length);

    //         payload = payload.replace(/\\u003C\\/g, "<");
    //         payload = payload.replace(/\\u003C/g, "<");
    //         payload = payload.replace(/\\\"/g, "\"");
    //         payload = unescape(payload);

    //         $("#dataFBLang").html(payload);

    //         var lang = $("#new_language").find('option[selected="1"]').text();
    //         if (lang.indexOf("English") >= 0) language = "en";
    //         else if (lang.indexOf("Deutsch") >= 0) language = "de";
    //         log('Facebook language is "' + lang + '"');

    //         $("#dataFBLang").html("");
    //         handler(hdata);
    //     });
    // });
}

// =============================================================================
// Loads a language-dependent content page.
// Parameters:
//      lang:       "de" for German or "en" for English
//      handler:    Function to be called when done (accepts one parameter)
//      hdata:      Data to be passed to the handler function

function loadLanguageContent(lang, handler, hdata) {
    log("LOADING LANGUAGE CONTENT");
    $("#mainContainer").load("content_" + lang + ".html", function(response, status, xhr) {
        $("#mainContainer").html(response);
        handler(hdata);
    });
}

// =============================================================================
// Translates a resource string.
// Parameters:
//      theString:      The resource string to translate
// Return value:
//      The language-dependent version of the given resource string.

function resStr(theString) {
    var langs = theString.split("@");
    for (var i = 0; i < langs.length; i++) {
        if (langs[i].indexOf(language.toUpperCase() + ":") === 0) {
            return langs[i].substring(language.length + 1);
        }
    }

    // no language support at the moment, stub for future use
    return theString;
}

// =============================================================================
var ids_BirthdayVisibility = "EN:Visibility of birthday@DE:Sichtbarkeit des Geburtstages";

var ids_RestoreNoData = "EN:You need to enter data to be restored first.@DE:Sie m&uuml;ssen zuerst die Daten eingeben, die Sie wiederherstellen m&ouml;chten.";
var ids_RestoreInvalidData = "EN:The data you have entered has an invalid format.@DE:Die Daten, die Sie eingegeben haben, besitzen ein ung&uuml;ltiges Format.";
var ids_NotAvailable = "EN:not available@DE:nicht verf&uuml;gbar";

var ids_Yes = "EN:Yes@DE:Ja";
var ids_No = "EN:No@DE:Nein";
var ids_Delete = "EN:Delete@DE:L&ouml;schen";

var ids_RemminderFlag = "EN:Comment it!@DE:ROSE Kommentare";

var ids_CommentBoxTitle = "EN:Enter comment@DE:Kommentar eingeben";
var ids_CommentBoxCommentButton = "EN:Comment@DE:Kommentieren";
var ids_CommentBoxCancelButton = "EN:Cancel@DE:Abbrechen";
var ids_CommentBoxHeadline = "EN:Explain why you like or dislike something, why you wrote a comment instead of liking an item or why you thought twice about posting or sharing something. This is the place to write down what you are disturbed or glad about, what annoyed you or what you liked and so on.@DE:Erklärt warum Euch etwas gefällt oder eben nicht gefällt, warum ihr einen Kommentar schreibt statt 'Gefällt mir' zu drücken oder warum ihr Euch zwei Mal überlegt habt etwas zu posten oder zu sharen. Hier ist Platz für alles, was euch stört oder gefällt, ärgert oder freut, etc.";
var ids_CommentBoxPlaceholder = "EN:Briefly describe what you are commenting on. What do you think?@DE:Beschreibe kurz was du kommentierst. Was denkst Du darüber?";

var ids_Type_CreateStatusPost = "EN:Status post creation@DE:Erstellung eines Beitrags";
var ids_Type_CreateImageStatusPost = "EN:Image status post creation@DE:Erstellung eines Photo-Beitrags";
var ids_Type_LikeStoryItem = "EN:Story item liking@DE:'Gef&auml;llt mir' bei einem Beitrag";
var ids_Type_UnlikeStoryItem = "EN:Revocation of story item like@DE:'Gef&auml;llt mir nicht mehr' bei einem Beitrag";
var ids_Type_DeleteComment = "EN:Story item comment deletion@DE:L&ouml;schung eines Kommentars";
var ids_Type_LikeComment = "EN:Story item comment liking@DE:'Gef&auml;llt mir' bei einem Kommentar";
var ids_Type_UnlikeComment = "EN:Revocation of status post comment like@DE:'Gef&auml;llt mir nicht mehr' bei einem Kommentar";
var ids_Type_ChangeStatusPostPrivacy = "EN:Change of status post privacy@DE:&Auml;nderung des Publikums eines Beitrags";
var ids_Type_CreateComment = "EN:Creation of a comment on a story item@DE:Kommentierung eines Beitrags";
var ids_Type_ShareStoryItem = "EN:Story item sharing@DE:Teilen eines Beitrags";
var ids_Type_DeleteStoryItem = "EN:Story item deletion@DE:L&ouml;schen eines Beitrags";
var ids_Type_Unfriend = "EN:Friendship revocation@DE:Entfernen eines Freunds";
var ids_Type_FriendRequest = "EN:Friendship request@DE:Verschicken einer Freundschaftsanfrage";
var ids_Type_AbortFriendRequest = "EN:Friendship request cancellation@DE:Abbrechen einer Freundschaftsanfrage";
var ids_Type_NewPhotoAlbum = "EN:Photo album creation@DE:Erstellen eines Fotoalbums";
var ids_Type_UploadPhoto = "EN:Photo upload@DE:Hochladen eines Fotos";
var ids_Type_DeletePhotoAlbum = "EN:Photo album deletion@DE:L&ouml;schen eines Fotoalbums";
var ids_Type_ChangePhotoAlbumPrivacy = "EN:Change of photo album privacy@DE:&Auml;nderung des Publikums eines Photoalbums";
var ids_Type_DeletePhoto = "EN:Photo deletion@DE:L&ouml;schen eines Fotos";
var ids_Type_LikePhotoAlbum = "EN:Photo album liking@DE:'Gef&auml;llt mir' bei einem Photoalbum";
var ids_Type_UnlikePhotoAlbum = "EN:Revocation of photo album like@DE:'Gef&auml;llt mir nicht mehr' bei einem Photoalbum";
var ids_Type_SharePhotoAlbum = "EN:Photo album sharing@DE:Teilen eines Photoalbums";
var ids_Type_OpenFacebook = "EN:Opening Facebook@DE:&Ouml;ffnen von Facebook";
var ids_Type_CloseFacebook = "EN:Closing Facebook@DE:Schlie&szlig;en von Facebook";
var ids_Type_Unknown = "EN:unknown@DE:unbekannt";
var ids_Type_FriendAccepted = "EN:Friend request accepted@DE:Freundschaftsanfrage bestätigt";
var ids_Type_FriendIgnored = "EN:Friend request ignored@DE:Freundschaftsanfrage ignoriert";
var ids_Type_FriendAdded = "EN:Friend request send@DE:Freundschaftsanfrage verschickt";
var ids_Type_ChatTurnedOff = "EN:Chat turned off@DE:Chat deaktiviert";
var ids_Type_ChatActivated = "EN:Chat activated@DE:Chat aufgerufen";
var ids_Type_Chat = "EN:Chat message@DE:Chatnachricht";
var ids_Type_HideActivity = "EN:Hide status@DE:Status verborgen";

var ids_ObjType_StatusPost = "EN:Status post@DE:Beitrag";
var ids_ObjType_Photo = "EN:Photo@DE:Foto";
var ids_ObjType_Comment = "EN:Comment@DE:Kommentar";
var ids_ObjType_Message = "EN:Message@DE:Nachricht";
var ids_ObjType_Unknown = "EN:unknown@DE:unbekannt";

var ids_InteractionNo = "EN:Interaction #@DE:Interaktion #";
var ids_Type = "EN:Type:@DE:Typ:";
var ids_PhotoID = "EN:Photo ID:@DE:ID des Fotos:";
var ids_StatusPostID = "EN:Status Post ID:@DE:ID des Beitrags:";
var ids_AlbumID = "EN:Album ID:@DE:ID des Fotoalbums:";
var ids_ObjectOwner = "EN:Object owner:@DE:Objektbesitzer:";
var ids_ObjectType = "EN:Object type:@DE:Objekttyp:";
var ids_PrivacySetting = "EN:Privacy setting:@DE:Privatsp&auml;reeinstellung:";
var ids_PreviousPrivacySetting = "EN:Previous privacy setting:@DE:Vorherige Privatsp&auml;reeinstellung:";
var ids_TargetUser = "EN:Target user:@DE:Zielbenutzer:";

var ids_Comment = "EN:Comment #@DE:Kommentar #";
var ids_ReferencedObject = "EN:Referenced object:@DE:Referenziertes Objekt:";
var ids_Content = "EN:Content:@DE:Inhalt:";
var ids_Timestamp = "EN:Timestamp:@DE:Zeitstempel:";
var ids_PrivacyScope = "EN:Privacy scope:@DE:Privatsp&auml;re:";

var ids_PrivacyScopeUnknown = "EN:Unknown privacy scope@DE:Unbekannte Privatsp&auml;reeinstellung";
var ids_PrivacyScopeCustom = "EN:Custom@DE:Benutzerdefiniert";
var ids_PrivacyScopePublic = "EN:Public@DE:Öffentlich";
var ids_PrivacyScopeFriends = "EN:Friends@DE:Freunde";
var ids_PrivacyScopeOnlyMe = "EN:Only user@DE:Nur Proband";

var ids_PrivacyInterfacePostScope = "EN:Who can see your future posts?@DE:Wer kann deine zukünftigen Beiträge sehen?";
var ids_PrivacyInterfaceFindContact = "EN:Who can look you up using the email address or phone number you provided?@DE:Wer kann dich anhand der von dir angegebenen E-Mail-Adresse oder Telefonnummer finden?";
var ids_PrivacyInterfaceSearchEngine = "EN:Do you want other search engines to link to your timeline?@DE:Möchtest du, dass andere Suchmaschinen einen Link zu deiner Chronik enthalten?";

var ids_PrivacyInterfacePosting = "EN:Who can post on your timeline?@DE:Wer kann in deiner Chronik posten?";
var ids_PrivacyInterfaceReview = "EN:Review posts friends tag you in before they appear on your timeline?@DE:Möchtest du Beiträge, in denen dich deine Freunde markieren, prüfen, bevor sie in deiner Chronik erscheinen?";
var ids_PrivacyInterfaceTagging = "EN:Who can see posts you've been tagged in on your timeline?@DE:Wer kann Beiträge, in denen du markiert wurdest, in deiner Chronik sehen?";
var ids_PrivacyInterfaceOthers = "EN:Who can see what others post on your timeline?@DE:Wer kann sehen, was andere in deiner Chronik posten?";
var ids_PrivacyInterfaceTagReview = "EN:Review tags people add to your own posts before the tags appear on Facebook?@DE:Möchtest du die Markierungen überprüfen, die Nutzer zu deinen eigenen Beiträgen hinzufügen, bevor sie auf Facebook erscheinen?";
var ids_PrivacyInterfaceExpansion = "EN:When you’re tagged in a post, who do you want to add to the audience if they aren’t already in it?@DE:Wen möchtest du zu dem Publikum hinzufügen, der noch nicht Teil davon ist, wenn du in einem Beitrag markiert wirst?";
var ids_PrivacyInterfaceSuggestions = "EN:Who sees tag suggestions when photos that look like you are uploaded?@DE:Wer kann Markierungsvorschläge sehen, wenn Fotos hochgeladen werden, die dir ähneln?";

// =============================================================================
// Formats a version number (pretty printing)
// Parameters:
//      - version:      The nersion number to format
// Return value:
//      The formatted version number

function formatVersion(version) {
    // Remove leading and trailing whitespace characters
    while (version.substr(0, 1) == " ") {
        version = version.substr(1);
    }
    while (version.substr(version.length - 1, version.length) == " ") {
        version = version.substr(0, version.length - 1);
    }

    // Remove the outer dollar signs
    if (version.substr(0, 1) == "$") {
        version = version.substr(1);
    }
    if (version.substr(version.length - 1, version.length) == "$") {
        version = version.substr(0, version.length - 1);
    }

    return version;
}

// =============================================================================

function getRevisionNumber() {
    if (REV === null) {
        return "error reading revision number";
    }

    var revisions = REV.match(/[0-9]+/g);

    if (revisions.length === 0) {
        return "error reading revision number";
    } else {
        return revisions[revisions.length - 1];
    }
}

// Initializes the version information display in the GUI

function initializeVersionInfo() {
    try {
        // Get extension info.
        var extensionInfo = kango.getExtensionInfo();

        // Get version number.
        var versionNumber = extensionInfo.version;

        // Display it.
        $("#versionInformation").text(versionNumber);
    } catch (exception) {
        // Something went wrong.
        log("Error while retrieving plugin data.");

        // Use revision number instead.
        $("#versionInformation").text("Rev " + getRevisionNumber());
    }
}

// =============================================================================
// =============================================================================
// Check if an object is empty or not
// Parameters:
//      - obj:      A javascript object - NOT an javascript array
// Return value:
//      true or false
var isEmpty;
isEmpty = function(obj) {
    var key;
    for (key in obj) {
        return false;
    }
    return true;
};

// =============================================================================
// Checks whether there is a main menu on the current page and initializes it if
// there is one.

function initializeMenu() {
    try {
        // Hide the pages we do not need at the moment
        hideAllPages(false);

        // Find the links in the main menu
        var aboutLink = $("#menuLinkAbout");
        var helpLink = $("#menuLinkHelp");
        var interactionsLink = $("#menuLinkInteractions");
        var commentsLink = $("#menuLinkComments");
        var deleteLink = $("#menuLinkDelete");
        var privacyLink = $("#menuLinkPrivacy");
        var backupLink = $("#menuLinkBackup");
        var diaryLink = $("#menuLinkDiary");
        var settingsLink = $("#menuLinkSettings");

        if (!aboutLink || aboutLink.length < 1) {
            throw new Error("Could not find ABOUT link in menu");
        }
        if (!helpLink || helpLink.length < 1) {
            throw new Error("Could not find HELP link in menu");
        }
        if (!interactionsLink || interactionsLink.length < 1) {
            throw new Error("Could not find INTERACTIONS link in menu");
        }
        if (!commentsLink || commentsLink.length < 1) {
            throw new Error("Could not find STUDY COMMENTS link in menu");
        }
        if (!deleteLink || deleteLink.length < 1) {
            throw new Error("Could not find DELETE link in menu");
        }
        if (!privacyLink || privacyLink.length < 1) {
            throw new Error("Could not find PRIVACY link in menu");
        }
        if (!backupLink || backupLink.length < 1) {
            throw new Error("Could not find BACKUP link in menu");
        }
        if (!diaryLink || diaryLink.length < 1) {
            throw new Error("Could not find DIARY link in menu");
        }
        if (!settingsLink || settingsLink.length < 1) {
            throw new Error("Could not find SETTINGS link in menu");
        }

        aboutLink.click(function() {
            hideAllPages(true);
            $('#about-page').show();
            $('#menuItemAbout').prop("class", "active");
        });
        helpLink.click(function() {
            hideAllPages(true);
            $('#help-page').show();
            $('#menuItemHelp').prop("class", "active");
        });
        interactionsLink.click(function() {
            hideAllPages(true);
            $('#interactions-page').show();
            $('#menuItemInteractions').prop("class", "active");

            displayInteractions();
        });
        commentsLink.click(function() {
            hideAllPages(true);
            $('#comments-page').show();
            $('#menuItemComments').prop("class", "active");

            displayComments();
        });
        deleteLink.click(function() {
            hideAllPages(true);
            $('#delete-page').show();
            $('#menuItemDelete').prop("class", "active");
        });
        privacyLink.click(function() {
            hideAllPages(true);
            $('#privacy-page').show();
            $('#menuItemPrivacy').prop("class", "active");

            checkPrivacySettings();
        });
        backupLink.click(function() {
            hideAllPages(true);
            $('#backup-page').show();
            $('#menuItemBackup').prop("class", "active");
        });
        diaryLink.click(function() {
            hideAllPages(true);
            $('#diary-page').show();
            $('#menuItemDiary').prop("class", "active");
        });
        settingsLink.click(function() {
            hideAllPages(true);
            $('#settings-page').show();
            $('#menuItemSettings').prop("class", "active");
        });

        // Set the handlers for the controls on the "privacy" page
        var loadPrivacyBtn = $("#btnLoadPrivacySettings");
        var delPrivacyBtn = $("#btnDeletePrivacySettings");

        if (!loadPrivacyBtn || loadPrivacyBtn.length < 1) {
            throw new Error("Could not find LOAD PRIVACY button");
        }
        if (!delPrivacyBtn || delPrivacyBtn.length < 1) {
            throw new Error("Could not find DELETE PRIVACY button");
        }

        loadPrivacyBtn.click(function() {
            loadPrivacySettings(displayPrivacySettings);
        });
        delPrivacyBtn.click(function() {
            kango.invokeAsync('kango.storage.removeItem', 'privacy');
            displayPrivacySettings(null);
        });

        // Set the handlers for the controls on the "delete" page
        var delInteractionsBtn = $("#btnDeleteInteractions");
        var delInteractionsModalBtn = $("#btnDeleteInteractionsModal");
        var delCommentsBtn = $("#btnDeleteComments");
        var delCommentsModalBtn = $("#btnDeleteCommentsModal");

        if (!delInteractionsBtn || delInteractionsBtn.length < 1) {
            throw new Error("Could not find DELETE INTERACTIONS button");
        }
        if (!delInteractionsModalBtn || delInteractionsModalBtn.length < 1) {
            throw new Error("Could not find DELETE INTERACTIONS MODAL button");
        }
        if (!delCommentsBtn || delCommentsBtn.length < 1) {
            throw new Error("Could not find DELETE COMMENTS button");
        }
        if (!delCommentsModalBtn || delCommentsModalBtn.length < 1) {
            throw new Error("Could not find DELETE COMMENTS MODAL button");
        }

        delInteractionsBtn.click(function() {
            $("#delete-interactions-confirm").modal('show');
        });
        delInteractionsModalBtn.click(function() {
            deleteInteractions();
            $("#delete-interactions-confirm").modal('hide');
        });
        delCommentsBtn.click(function() {
            $("#delete-comments-confirm").modal('show');
        });
        delCommentsModalBtn.click(function() {
            deleteComments();
            $("#delete-comments-confirm").modal('hide');
        });

        // Set the handlers for the controls on the "backup and restore" page
        var backupBtn = $("#btnBackup");
        var restoreBtn = $("#btnRestore");
        var emailBtn = $("#btnSendMail");
        var cancelBackupBtn = $("#btnCancelBackup");

        if (!backupBtn || backupBtn.length < 1) {
            throw new Error("Could not find BACKUP button");
        }
        if (!restoreBtn || restoreBtn.length < 1) {
            throw new Error("Could not find RESTORE button");
        }
        if (!emailBtn || emailBtn.length < 1) {
            throw new Error("Could not find EMAIL button");
        }
        if (!cancelBackupBtn || cancelBackupBtn.length < 1) {
            throw new Error("Could not find BACKUP CLEAR FIELD button");
        }

        backupBtn.click(function() {
            createBackup();
        });
        restoreBtn.click(function() {
            restoreBackup();
        });
        emailBtn.click(function() {
            emailStudyData();
        });
        cancelBackupBtn.click(function() {
            $("#txtBackup").val("");
        });

        // Set the handlers for the controls on the "diary" page
        diaryLink.click(function() {
            loadDiary();
        });


        // FIXME: REMOVE FUNCTION OUT OF INIT FUNCTION!

        function loadDiary() {
            $("#diaryItems").children().remove();

            kango.invokeAsync('kango.storage.getItem', 'diary', function(data) {
                var arr = [];

                if (data !== "null") {
                    arr = data;
                }

                for (var i = 0; i < arr.length; i++) {
                    var diaryItem = arr[i];

                    var string = "<dt>" + new Date(diaryItem.date).toLocaleString() + "</dt><dd class='span12'>" + diaryItem.comment + "</dd>";
                    $("#diaryItems").append(string);
                }
            });
        }

        function deleteDiary() {
            $("#diaryItems").children().remove();

            kango.invokeAsync('kango.storage.removeItem', 'diary');
        }

        // FIXME: REMOVE FORM AND USE CLICK EVENTHANDLER / NO SUBMIT!
        $("#diaryForm").submit(

        function(event) {
            // don't reload page at submit
            event.preventDefault();

            if ($("#diaryTextarea").val() === '') {
                $("#diaryForm > fieldset > .control-group").addClass("error box-shadow");
                $("#diaryErrorOne").show();
                return false;
            }

            $("#diaryForm > fieldset > .control-group").removeClass("error box-shadow");
            $("#diaryErrorOne").hide();

            var entry = $("#diaryTextarea").val();

            var diaryItem = {};
            diaryItem["date"] = new Date();
            diaryItem["comment"] = entry;

            kango.invokeAsync('kango.storage.getItem', 'diary', function(data) {
                var diary = [];

                if (data !== "null") {
                    diary = data;
                }

                diary.push(diaryItem);

                kango.invokeAsync('kango.storage.setItem', 'diary', diary);

                loadDiary();
            });

            $("#diaryTextarea").val('');
        });

        $("#diaryCancelButton").click(

        function() {
            $("#diaryTextarea").val('');
        });

        $("#diaryDeleteButton").click(

        function() {
            $("#mymodal").modal('show');
        });

        $("#diaryDeleteButtonModal").click(

        function() {
            deleteDiary();
            $("#mymodal").modal('hide');
        });

        // set event handler for settings page
        var reminderBox = $("#inputReminder");
        reminderBox.change(function() {
            setReminderState($(this).is(":checked"));
        });
        kango.invokeAsync("kango.storage.getItem", "rose-settings", function(settings) {
            reminderBox.attr("checked", settings.reminder);
        });

    } catch (ex) {
        log("User interface initialization failed: " + ex);
    }
}

// =============================================================================
// Hides all content pages in the user interface

function hideAllPages(mainPage) {
    if (mainPage) {
        $('#main-page').hide();
    }

    $('#about-page').hide();
    $('#menuItemAbout').prop("class", "");

    $('#help-page').hide();
    $('#menuItemHelp').prop("class", "");

    $('#interactions-page').hide();
    $('#menuItemInteractions').prop("class", "");

    $('#comments-page').hide();
    $('#menuItemComments').prop("class", "");

    $('#delete-page').hide();
    $('#menuItemDelete').prop("class", "");

    $('#privacy-page').hide();
    $('#menuItemPrivacy').prop("class", "");

    $('#backup-page').hide();
    $('#menuItemBackup').prop("class", "");

    $('#diary-page').hide();
    $('#menuItemDiary').prop("class", "");

    $('#settings-page').hide();
    $('#menuItemSettings').prop("class", "");
}

// =============================================================================
// Fetches the stored interactions from the background script and displays them
// in the graphical user interface.
// Parameters:
//      data:   The array of stored interactions or null if it still needs to be
//              loaded.

function displayInteractions(data) {
    try {
        if (!data) {
            if (window.getInteractionData) {
                log("Interaction data NOT available, loading...");
                window.getInteractionData(displayInteractions);
            } else {
                log("Interaction data NOT available, setting handler...");
                window.interactionDataHandler = displayInteractions;
            }
        } else {
            log("Interaction data available.");
            $("#loadingTextInteractions").show();

            // If we don't have any interactions yet, we display a cooresponding hint
            if (data.length === 0) {
                $("#interactionList").hide();
                $("#interactionsLabel").hide();
                $("#noInteractions").show();
            } else {
                $("#interactionList").show();
                $("#interactionsLabel").show();
                $("#noInteractions").hide();
            }

            // Clear the interaction list
            $("#interactionList").find("li").each(function() {
                $(this).remove();
            });

            // Create an element for every interaction object we have
            var idSet = false;
            log("Loading interaction list...");
            for (var i = 0; i < data.length; i++) {
                var inter = data[i];

                // Check, if interaction should be skipped (open-close-events).
                if (!SHOW_OPEN_CLOSE_INTERACTIONS && (inter["interaction_type"] == "openFacebook" || inter["interaction_type"] == "closeFacebook")) {
                    continue;
                }

                // Create a new element in the list
                var elemLI = $(document.createElement('li')).html(resStr(ids_InteractionNo) + inter["nr"] + "&nbsp;").prop("class", "interactionItem").appendTo($("#interactionList"));

                var deleteButton = $(document.createElement('span')).html(resStr(ids_Delete)).addClass("badge badge-important").prop("interaction", inter["nr"]).css("cursor", "pointer").on("click", function() {
                    // Remove interaction.
                    removeInteraction($(this).prop("interaction"));

                    // Display interactions again.
                    displayInteractions();
                });
                deleteButton.appendTo(elemLI);

                // Create a the list for the interaction data
                var elemUL = $(document.createElement('ul')).appendTo(elemLI);

                // Append the data values
                log("Displaying interaction " + i + " of " + data.length + "...");
                $(document.createElement('li')).html(resStr(ids_Type) + " " + formatInteractionType(inter)).prop("class", "interactionData").appendTo(elemUL);
                if (inter["object_id"]) {
                    $(document.createElement('li')).html(resStr(ids_ReferencedObject) + " " + inter["object_id"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["status_post_id"]) {
                    $(document.createElement('li')).html(resStr(ids_StatusPostID) + " " + inter["status_post_id"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["photo_id"]) {
                    $(document.createElement('li')).html(resStr(ids_PhotoID) + " " + inter["photo_id"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["album_id"]) {
                    $(document.createElement('li')).html(resStr(ids_AlbumID) + " " + inter["album_id"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["object_owner"]) {
                    $(document.createElement('li')).html(resStr(ids_ObjectOwner) + " " + inter["object_owner"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["object_type"]) {
                    $(document.createElement('li')).html(resStr(ids_ObjectType) + " " + formatObjectType(inter)).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["privacy"]) {
                    $(document.createElement('li')).html(resStr(ids_PrivacySetting) + " " + inter["privacy"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["old_privacy"]) {
                    $(document.createElement('li')).html(resStr(ids_PreviousPrivacySetting) + " " + inter["old_privacy"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["content"]) {
                    $(document.createElement('li')).html(resStr(ids_Content) + " " + inter["content"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["target_user"]) {
                    $(document.createElement('li')).html(resStr(ids_TargetUser) + " " + inter["target_user"]).prop("class", "interactionData").appendTo(elemUL);
                }
                if (inter["privacy_scope"]) {
                    $(document.createElement('li')).html(resStr(ids_PrivacyScope) + " " + formatPrivacyScope(inter)).prop("class", "interactionData").appendTo(elemUL);
                }
                $(document.createElement('li')).html(resStr(ids_Timestamp) + " " + inter["time"]).prop("class", "interactionData").appendTo(elemUL);

            }

            // Display the proband ID for the first record
            kango.invokeAsync('kango.storage.getItem', 'rose-userid', function(data) {
                return $('#probandIDInteractions').html(data);
            });

            log("Interaction list loaded.");
            $("#loadingTextInteractions").hide();
        }
    } catch (ex) {
        log("Could not display interaction data: " + ex);
    }
}

// =============================================================================
// Fetches the study comments stored by the background script and displays them
// in the graphical user interface.
// Parameters:
//      data:   The array of stored comments or null if it still needs to be
//              loaded.

function displayComments(data) {
    try {
        if (!data) {
            if (window.getCommentData) {
                window.getCommentData(displayComments);
            } else {
                window.commentDataHandler = displayComments;
            }
        } else {
            $("#loadingTextComments").show();

            // If we don't have any comments yet, we display a cooresponding hint
            if (isEmpty(data)) {
                $("#commentList").hide();
                $("#commentsLabel").hide();
                $("#noComments").show();
            } else {
                $("#commentList").show();
                $("#commentsLabel").show();
                $("#noComments").hide();
            }

            // Clear the interaction list
            $("#commentList").find("li").each(function() {
                $(this).remove();
            });

            for (var key in data) {
                value = data[key];

                var listItem = $(document.createElement('li')).html(resStr(ids_Comment) + "<strong>" + key + " </strong>").addClass('commentItem').appendTo($("#commentList"));

                var deleteButton = $(document.createElement('span')).html(resStr(ids_Delete)).addClass("badge badge-important").prop("id", key).css("cursor", "pointer").on("click", function() {
                    // Remove interaction.
                    var id = $(this).prop("id");
                    removeComment(id);

                    // Display interactions again.
                    displayComments();
                });

                deleteButton.appendTo(listItem);
                var text = value["comment"];
                var date = new Date(value["date"]).toLocaleString();
                listItem.append("<blockquote><p>" + date + "<br>" + $.trim(text) + "</p></blockquote>");

            }

            // Create an element for every interaction object we have
            var idSet = false;
            for (var i = 0; i < data.length; i++) {
                var cmt = data[i];

                // Create a new element in the list
                var elemLI = $(document.createElement('li')).html(resStr(ids_CommentNo) + (i + 1)).prop("class", "commentItem").appendTo($("#commentList"));

                // Create a the list for the interaction data
                var elemUL = $(document.createElement('ul')).appendTo(elemLI);

                // Append the data values
                $(document.createElement('li')).html(resStr(ids_ReferencedObject) + " " + cmt["object_id"]).prop("class", "commentData").appendTo(elemUL);
                if (cmt["object_type"]) {
                    $(document.createElement('li')).html(resStr(ids_ObjectType) + " " + formatObjectType(cmt)).prop("class", "interactionData").appendTo(elemUL);
                }
                $(document.createElement('li')).html(resStr(ids_Content) + " " + cmt["content"]).prop("class", "commentData").appendTo(elemUL);
                $(document.createElement('li')).html(resStr(ids_Timestamp) + " " + cmt["time"]).prop("class", "commentData").appendTo(elemUL);

                // Display the proband ID for the first record
                if (!idSet) {
                    if (!cmt["proband_id"] || (cmt["proband_id"] === "")) {
                        log("ERROR: No proband ID in comment record");
                    } else {
                        idSet = true;
                        log("Proband ID: " + cmt["proband_id"]);
                        $('#probandIDComments').html(cmt["proband_id"]);
                    }
                }
            }

            kango.invokeAsync('kango.storage.getItem', 'rose-userid', function(data) {
                return $('#probandIDComments').html(data);
            });

            $("#loadingTextComments").hide();
        }
    } catch (ex) {
        log("Could not display comment data: " + ex);
    }
}

// =============================================================================
// Formats an interaction type into a human-readable string
// Parameters:
//      interaction:    The interaction for which to get the type string.
// Return value:
//      A human-readable string for the type of the given interaction object.

function formatInteractionType(interaction) {
    if (interaction["interaction_type"] == "updatestatus") {
        return resStr(ids_Type_CreateStatusPost);
    } else if (interaction["interaction_type"] == "updatestatuspicture") {
        return resStr(ids_Type_CreateImageStatusPost);
    } else if (interaction["interaction_type"] == "like" && interaction["object_type"] == "status") {
        return resStr(ids_Type_LikeStoryItem);
    } else if (interaction["interaction_type"] == "unlike" && interaction["object_type"] == "status") {
        return resStr(ids_Type_UnlikeStoryItem);
    } else if (interaction["interaction_type"] == "deleteComment") {
        return resStr(ids_Type_DeleteComment);
    } else if (interaction["interaction_type"] == "like" && interaction["object_type"] == "comment") {
        return resStr(ids_Type_LikeComment);
    } else if (interaction["interaction_type"] == "unlike" && interaction["object_type"] == "comment") {
        return resStr(ids_Type_UnlikeComment);
    } else if (interaction["interaction_type"] == "commentstatus") {
        return resStr(ids_Type_CreateComment);
    } else if (interaction["interaction_type"] == "share") {
        return resStr(ids_Type_ShareStoryItem);
    } else if (interaction["interaction_type"] == "deletestatus") {
        return resStr(ids_Type_DeleteStoryItem);
    } else if (interaction["interaction_type"] == "unfriend") {
        return resStr(ids_Type_Unfriend);
    } else if (interaction["interaction_type"] == "openFacebook") {
        return resStr(ids_Type_OpenFacebook);
    } else if (interaction["interaction_type"] == "closeFacebook") {
        return resStr(ids_Type_CloseFacebook);
    } else if (interaction["interaction_type"] == "friendaccepted") {
        return resStr(ids_Type_FriendAccepted);
    } else if (interaction["interaction_type"] == "friendignored") {
        return resStr(ids_Type_FriendIgnored);
    } else if (interaction["interaction_type"] == "friendadded") {
        return resStr(ids_Type_FriendAdded);
    } else if (interaction["interaction_type"] == "chatturnoff") {
        return resStr(ids_Type_ChatTurnedOff);
    } else if (interaction["interaction_type"] == "chatactivated") {
        return resStr(ids_Type_ChatActivated);
    } else if (interaction["interaction_type"] == "chat") {
        return resStr(ids_Type_Chat);
    } else if (interaction["interaction_type"] == "hideactivity") {
        return resStr(ids_Type_HideActivity);
    } else {
        log('Unknown interaction type: "' + interaction["interaction_type"] + '"');
        return resStr(ids_Type_Unknown);
    }
}

// Formats an privacy scope into a human-readable string
// Parameters:
//      interaction:    The interaction for which to get the privacy scope string.
// Return value:
//      A human-readable string for the privacy scope of the given interaction object.

function formatPrivacyScope(interaction) {
    if (interaction["privacy_scope"] == "custom") {
        return resStr(ids_PrivacyScopeCustom);
    } else if (interaction["privacy_scope"] == "public") {
        return resStr(ids_PrivacyScopePublic);
    } else if (interaction["privacy_scope"] == "only me") {
        return resStr(ids_PrivacyScopeOnlyMe);
    } else if (interaction["privacy_scope"] == "friends") {
        return resStr(ids_PrivacyScopeFriends);
    } else {
        log("Unknown privacy scope: " + interaction["privacy_scope"]);
        return resStr(ids_PrivacyScopeUnknown);
    }
}

// =============================================================================
// Formats an object type into a human-readable string
// Parameters:
//      interaction:    The interaction for which to get the object type string.
// Return value:
//      A human-readable string for the type of the given interaction object's
//      target type.

function formatObjectType(interaction) {
    if (interaction["object_type"] == "status") {
        return resStr(ids_ObjType_StatusPost);
    } else if (interaction["object_type"] == "photo") {
        return resStr(ids_ObjType_Photo);
    } else if (interaction["object_type"] == "comment") {
        return resStr(ids_ObjType_Comment);
    } else if (interaction["object_type"] == "message") {
        return resStr(ids_ObjType_Message);
    } else {
        log('Unknown object type: "' + interaction["object_type"] + '"');
        return resStr(ids_ObjType_Unknown);
    }
}

// =============================================================================
// Deletes all interactions stored in the database.

function deleteInteractions() {
    try {
        if (!window.deleteInteractionData) {
            throw new Error("ROSE not available");
        }
        window.deleteInteractionData();
    } catch (ex) {
        log("Could not delete interactions: " + ex);
    }
}

// =============================================================================
// Deletes all study comments stored in the database.

function deleteComments() {
    try {
        if (!window.deleteInteractionData) {
            throw new Error("ROSE not available");
        }
        window.deleteCommentData();
    } catch (ex) {
        log("Could not delete study comments: " + ex);
    }
}

// =============================================================================
// Loads all Facebook privacy settings into a data object and then calls the
// given callback handler with it.
// Parameters:
//      handler:    The callback to be invoked with the loaded data.

function loadPrivacySettings(handler) {
    try {
        hidePrivacyElements();
        $("#loadingPrivacy").show();

        // Initialize the privacy object
        loadUserID(function() {
            if (user_id === null) {
                // We're not logged in or have no access to Facebook for
                // some other reason
                $("#loadingPrivacy").hide();
                $("#privacyNotAvailable").show();
                return;
            }

            // Load the basic privacy settings
            var privacy = {};

            log("Loading privacy settings...");
            loadPrivacyStandard(privacy);
            loadPrivacyTimeline(privacy);

            // Wait for all privacy settings to be loaded
            log("Waiting for privacy callbacks to return...");
            waitForPrivacySettings(privacy, function(data) {
                // Write the data into the backstore
                kango.invokeAsync('kango.storage.setItem', 'privacy', privacy);
                log("Privacy settings written to storage.");

                handler(data);
            });
            log("Privacy settings loader complete.");
        });
    } catch (ex) {
        log("Could not load privacy settings: " + ex);
    }
}

// =============================================================================
// Checks whether all privacy settings have been loaded. If so, the given handler
// is called with the data object. Otherwise, the function waits.
// Parameters:
//      privacy:    The data object that receives the loaded values.
//      handler:    The callback to be invoked with the loaded data.

function waitForPrivacySettings(privacy, handler) {
    // Check whether all settings have been loaded
    if (privacy["standard"] && privacy["timeline"]) {
        log("All privacy settings loaded.");
        handler(privacy);
    } else window.setTimeout(function() {
            waitForPrivacySettings(privacy, handler);
        }, 500);
}

// =============================================================================
// Loads the Facebook user ID
// Parameters:
//      handler:    The callback to be invoked when the function has finished.

function loadUserID(handler) {
    $("#dataUserID").load("https://www.facebook.com/settings/?tab=privacy #pageNav", null, function(response, status, xhr) {

        // Extract the element containing the user ID
        var link = $(this).find("li.tinyman img.headerTinymanPhoto").prop("id");


        // If we don't find the link, we assume that we have no access to
        // Facebook at the moment.
        if (typeof link == "undefined") {
            log("Could not find user avatar - user ID not available");
            user_id = null;
            handler();
            return;
        }

        // Extract the user ID
        var uid = link.substring(link.indexOf("profile_pic_header_") + "profile_pic_header_".length);
        log("Found user ID: " + uid);

        // Set the user ID into the data object
        user_id = uid;
        $("#dataUserID").html("");
        handler();
    });
}

// =============================================================================
// - BEGIN OF PRIVACY SETTING LOADING -
// =============================================================================
// Converts a logical value into a string
// Parameters:
//      theBool:    The logical value to be converted into a string
// Return value:
//      A string corresponding to the given logical value

function boolToString(theBool) {
    if (theBool) {
        return resStr(ids_Yes);
    } else {
        return resStr(ids_No);
    }
}

// =============================================================================

function loadPrivacyStandard(privacy) {
    // Send AJAX request to privacy tab.
    $.ajax({
        url: 'http://www.facebook.com/settings/?tab=privacy'
    }).done(function(data) {
        // Get post scope.
        var post_scope = {
            'description': 'post-scope',
            'value': $("a[href*=composer] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get find-contact scope.
        var find_contact_scope = {
            'description': 'find-contact',
            'value': $("a[href*=findcontact] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get search-engine scope.
        var search_engine_scope = {
            'description': 'search-engine',
            'value': $("a[href*=search] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Initialize standard privacy array.
        privacy["standard"] = [];

        // Push settings to privacy array.
        privacy["standard"].push(post_scope);
        privacy["standard"].push(find_contact_scope);
        privacy["standard"].push(search_engine_scope);
    });
}

function loadPrivacyTimeline(privacy) {
    // Send AJAX request to timeline tab.
    $.ajax({
        url: 'http://www.facebook.com/settings/?tab=timeline'
    }).done(function(data) {
        // Get scope of who can post in your timeline.
        var posting = {
            'description': 'posting',
            'value': $("a[href*=posting] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get review scope.
        var review = {
            'description': 'review',
            'value': $("a[href*=review] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get tagging view scope.
        var tagging = {
            'description': 'tagging',
            'value': $("a[href*=tagging] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get scope of what people can post in your timeline.
        var post_others = {
            'description': 'post-others',
            'value': $("a[href*=others] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get scope of tag review.
        var tag_review = {
            'description': 'tag-review',
            'value': $("a[href*=tagreview] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get scope of expansion.
        var expansion = {
            'description': 'expansion',
            'value': $("a[href*=expansion] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Get suggestions of tag scope.
        var suggestions = {
            'description': 'suggestions',
            'value': $("a[href*=suggestions] .fbSettingsListItemContent .fwb", $(data)).html()
        };

        // Initialize timeline privacy array.
        privacy["timeline"] = [];

        // Push settings to privacy array.
        privacy["timeline"].push(posting);
        privacy["timeline"].push(review);
        privacy["timeline"].push(tagging);
        privacy["timeline"].push(post_others);
        privacy["timeline"].push(tag_review);
        privacy["timeline"].push(expansion);
        privacy["timeline"].push(suggestions);
    });
}

// =============================================================================
// - END OF PRIVACY SETTING LOADING -
// =============================================================================

function hidePrivacyElements() {
    // Hide the privacy controls
    $("#noPrivacySettings").hide();
    $("#privacyControls").hide();

    $("#privacySettingsDesc").hide();

    $("#privacyHeaderStandard").hide();
    $("#privacySettingsStandard").hide();

    $("#privacyHeaderTimeline").hide();
    $("#privacySettingsTimeline").hide();
}

// =============================================================================
// Check whether stored Facebook privacy settings are available and displays
// them if this is the case.
// Parameters:
//      privacy:    The privacy data or null if it has not been loaded yet

function checkPrivacySettings(privacy) {
    try {
        hidePrivacyElements();
        $("#loadingPrivacy").show();

        // Check whether we have stored privacy settings
        var hnd = function(data) {
            $("#loadingPrivacy").hide();

            // If no privacy data has been stored yet, we have nothing
            // to display.
            if ((typeof data == "undefined") || !data) {
                log("Stored privacy data NOT available");
            } else {
                log("Stored privacy data IS available");
            }

            displayPrivacySettings(data);
        };

        // If the parameter contains privacy settings, we take them. Otherwise,
        // we try to load them from the backstore.
        if ((typeof privacy != "undefined") && privacy) hnd(privacy);
        else kango.invokeAsync('kango.storage.getItem', 'privacy', hnd);
    } catch (ex) {
        log("Could not load privacy settings: " + ex);
    }
}

// =============================================================================
// Displays the privacy settings stored in the given data object.
// Parameters:
//      privacy:    The privacy data object to be displayed
/*function displayPrivacySettings(privacy) {
    hidePrivacyElements();
    log("Displaying privacy settings...");

    if ((typeof privacy == "undefined") || !privacy) {
        log("Privacy settings are null, aborting");
        $("#noPrivacySettings").show();
        $("#privacyControls").show();
        $("#loadingPrivacy").hide();
        return;
    }

    // Privacy language map
    var descriptionsPrivacy = {
        'post-scope': ids_PrivacyInterfacePostScope,
        'find-contact': ids_PrivacyInterfaceFindContact,
        'search-engine': ids_PrivacyInterfaceSearchEngine,
        'posting': ids_PrivacyInterfacePosting,
        'review': ids_PrivacyInterfaceReview,
        'tagging': ids_PrivacyInterfaceTagging,
        'post-others': ids_PrivacyInterfaceOthers,
        'tag-review': ids_PrivacyInterfaceTagReview,
        'expansion': ids_PrivacyInterfaceExpansion,
        'suggestions': ids_PrivacyInterfaceSuggestions
    };

    // Standard privacy settings
    for (var i = 0; i < privacy["standard"].length; i++) {
        var curPriv = privacy["standard"][i];
        var row = $(document.createElement('tr')).appendTo($("#privacySettingsStandard"));

        var description = curPriv["description"];
        // Check if resource string can be used.
        if(descriptionsPrivacy[description] != null) {
            description = resStr(descriptionsPrivacy[description]);
        }
        var value = curPriv["value"];

        $(document.createElement('td')).html(description).appendTo(row);
        $(document.createElement('td')).html(value).appendTo(row);
    }
    $("#privacyHeaderStandard").show();
    $("#privacySettingsStandard").show();

    // Timeline privacy settings
    for (var i = 0; i < privacy["timeline"].length; i++) {
        var curPriv = privacy["timeline"][i];
        var row = $(document.createElement('tr')).appendTo($("#privacySettingsTimeline"));

        var description = curPriv["description"];
        // Check if resource string can be used.
        if(descriptionsPrivacy[description] != null) {
            description = resStr(descriptionsPrivacy[description]);
        }
        var value = curPriv["value"];

        $(document.createElement('td')).html(description).appendTo(row);
        $(document.createElement('td')).html(value).appendTo(row);
    }
    $("#privacyHeaderTimeline").show();
    $("#privacySettingsTimeline").show();


    $("#privacySettingsDesc").show();
    $("#privacyControls").show();
    $("#loadingPrivacy").hide();
    log("Privacy settings displayed.");
}*/

function displayPrivacySettings(privacy) {
    var curPriv, row, description, value, i;

    hidePrivacyElements();
    log("Displaying privacy settings...");

    if ((typeof privacy == "undefined") || !privacy) {
        log("Privacy settings are null, aborting");
        $("#noPrivacySettings").show();
        $("#privacyControls").show();
        $("#loadingPrivacy").hide();
        return;
    }

    // Privacy language map
    var descriptionsPrivacy = {
        'post-scope': ids_PrivacyInterfacePostScope,
        'search-engine': ids_PrivacyInterfaceSearchEngine,
        'posting': ids_PrivacyInterfacePosting,
        'review': ids_PrivacyInterfaceReview,
        'tagging': ids_PrivacyInterfaceTagging,
        'post-others': ids_PrivacyInterfaceOthers,
        'tag-review': ids_PrivacyInterfaceTagReview,
        'expansion': ids_PrivacyInterfaceExpansion,
        'suggestions': ids_PrivacyInterfaceSuggestions
    };

    // Standard privacy settings
    for (i = 0; i < privacy["standard"].length; i++) {
        curPriv = privacy["standard"][i];
        row = $(document.createElement('tr')).appendTo($("#privacySettingsStandard"));

        description = curPriv["description"];
        // Check if resource string can be used.
        if (descriptionsPrivacy[description] !== undefined) {
            description = resStr(descriptionsPrivacy[description]);
        }
        value = curPriv["value"];

        $(document.createElement('td')).html(description).appendTo(row);
        $(document.createElement('td')).html(value).appendTo(row);
    }
    $("#privacyHeaderStandard").show();
    $("#privacySettingsStandard").show();

    // Timeline privacy settings
    for (i = 0; i < privacy["timeline"].length; i++) {
        curPriv = privacy["timeline"][i];
        row = $(document.createElement('tr')).appendTo($("#privacySettingsTimeline"));

        description = curPriv["description"];
        // Check if resource string can be used.
        if (descriptionsPrivacy[description] !== undefined) {
            description = resStr(descriptionsPrivacy[description]);
        }
        value = curPriv["value"];

        $(document.createElement('td')).html(description).appendTo(row);
        $(document.createElement('td')).html(value).appendTo(row);
    }
    $("#privacyHeaderTimeline").show();
    $("#privacySettingsTimeline").show();


    $("#privacySettingsDesc").show();
    $("#privacyControls").show();
    $("#loadingPrivacy").hide();
    log("Privacy settings displayed.");
}

// =============================================================================
// Gets the study data in the format selected on the Backup/Restore page
// Parameters:
//      handler:    The handler function to be called when the data is available
//      hndData:    Custom data to be passed to the handler

// Was zur HÖLLE IST DAS?
// FIXME: ONE DATA ELEMET FOR CONFIG ONE FOR SETTINGS

function getStudyData(handler) {
    kango.invokeAsync('kango.storage.getItem', 'privacy', function(privacy) {
        kango.invokeAsync('kango.storage.getItem', 'diary', function(diary) {
            kango.invokeAsync('kango.storage.getItem', 'rose-first-run', function(rosefirstrun) {
                kango.invokeAsync('kango.storage.getItem', 'rose-data-version', function(version) {
                    window.getInteractionData(function(interactions) {
                        window.getCommentData(function(comments) {
                            var container = {};
                            container["privacy"] = privacy;
                            container["interactions"] = interactions;
                            container["comments"] = comments;
                            container["diary"] = diary;
                            container["install-date"] = rosefirstrun;
                            container["export-date"] = new Date();
                            container["rose-data-version"] = version;

                            var backupData = "";
                            backupData = JSON.stringify(container, null, " ");

                            handler(backupData);
                            if (backupData !== "") {
                                $("#backup-error").hide();
                            }
                        });
                    });
                });
            });

        });
    });
}

function sanitizeComments(comments) {
    var key, parts, saniComments, value;

    saniComments = {};

    for (key in comments) {
        value = comments[key];
        if (value.hasOwnProperty('comment') && value.hasOwnProperty('date')) {
            saniComments[key] = value;
        } else {
            parts = value.split('~');
            saniComments[key] = {
                'comment': parts[1].trim(),
                'date': new Date(parts[0] * 1000)
            };
        }
    }
    return saniComments;
}

// =============================================================================
// Creates / exports a backup copy of the data currently stored in the ROSE plugin.

function createBackup() {
    getStudyData(function(data) {
        $("#txtBackup").val(data);
    });
}

// =============================================================================
// Restores the ROSE plugin data from a backup copy

function restoreBackup() {
    $("#txtBackup").removeClass("error box-shadow");
    $("#backup-error").hide();

    // Get the data from the text area
    var strData = $("#txtBackup").val();
    if ((typeof strData === undefined) || (strData === "")) {
        $("#txtBackup").addClass("error box-shadow");
        $("#backup-error").html(resStr(ids_RestoreNoData));
        $("#backup-error").show();
        return;
    }

    // Deserialize the JSON data
    var container = null;
    try {
        container = $.parseJSON(strData);
    } catch (ex) {
        log("Could not decode restore data: " + ex);
        container = null;
    }
    if (typeof container === undefined || container === null) {
        $("#txtBackup").addClass("error box-shadow");
        $("#backup-error").html(resStr(ids_RestoreInvalidData));
        $("#backup-error").show();
        return;
    }

    // Get the contents
    var interactions = container["interactions"];
    var comments = sanitizeComments(container["comments"]);
    var dataversion = container["rose-data-version"];
    if (interactions === null || comments === null) {
        $("#txtBackup").addClass("error box-shadow");
        $("#backup-error").html(resStr(ids_RestoreInvalidData));
        $("#backup-error").show();
        return;
    }

    var roseData = kango.storage.getItem("roseData");
    roseData["interactions"] = interactions;
    roseData["roseComments"] = comments;
    kango.storage.setItem("roseData", roseData);

    // Overwrite the stored data
    kango.invokeAsync('kango.storage.setItem', 'diary', container["diary"]);
    kango.invokeAsync('kango.storage.setItem', 'privacy', container["privacy"]);
    kango.invokeAsync('kango.storage.setItem', 'rose-data-version', dataversion);

    // Notify all instances.
    notifyStorageChanged();
    initStorage();
}

// =============================================================================
// Sends an e-mail containing the study data to the researchers

function emailStudyData() {
    getStudyData(function(data) {
        var link = "mailto:foo@bar.com?subject=ROSE Studiendaten" + "&body=" + encodeURIComponent(data);
        if ((window.location + "").indexOf("chrome-extension") === 0) {
            wnd = window.open(link);
        } else {
            window.location = link;
        }
    });
}

// =============================================================================